/*
 * Copyright (C) 2022, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

//
// Created by hxf on 22-8-25.
//

#ifndef UKUI_SIDEBAR_SIDEBAR_UI_CONFIG_H
#define UKUI_SIDEBAR_SIDEBAR_UI_CONFIG_H

#include <QObject>
#include <QWindow>
#include <QRect>
#include <QMap>

// 两种模式下侧边栏按钮区域的宽度
#define PC_SIDEBAR_WIDTH     384
#define TABLET_SIDEBAR_WIDTH 540

namespace Sidebar {

/**
 * 用于标识界面上的全部组件，访问组件的布局属性
 */
class LayoutComponent
{
    Q_GADGET
public:
    enum Component
    {
        Undefined = 0,
        SidebarMain,
        SidebarUserInfo,
        SidebarUserInfoIcon,
        SidebarUserInfoText,
        SidebarUserInfoPowerIcon,
        SidebarMenuButton,
        SidebarMenuButtonView,
        SidebarIconButton,
        SidebarIconButtonIcon,
        SidebarIconButtonView,
        SidebarProgressBar,
        SidebarProgressBarIcon,
        SidebarProgressBarSlider,
        SidebarProgressBarView,
        SidebarWeather,
        SidebarFoldShortcutArea,
        /* 通知中心 */
        NotificationItem,
        NotificationItemNormal,
        NotificationItemBody,
    };
    Q_ENUM(Component)
};

/**
 * 全局config对象，保存每个组件的布局数据，通过修改布局数据，实现动态布局切换
 */
class LayoutConfig : public QObject
{
    Q_OBJECT
public:
    static LayoutConfig *getInstance(QObject *parent = nullptr);
    ~LayoutConfig() override;

    Q_INVOKABLE int width(LayoutComponent::Component component);
    Q_INVOKABLE int height(LayoutComponent::Component component);
    Q_INVOKABLE int radius(LayoutComponent::Component component);
    Q_INVOKABLE int spacing(LayoutComponent::Component component);

    /**
     * @param component 组件id
     * @param position 表示左上右下 值: 0, 1, 2，3;
     * @return
     */
    Q_INVOKABLE int margin(LayoutComponent::Component component, int position); 

    Q_INVOKABLE bool isTabletMode();

Q_SIGNALS:
    void layoutChanged();
    void systemModeChanged(bool isTableMode);

private Q_SLOTS:
    void updateLayout(const QString &key);

private:
    explicit LayoutConfig(QObject *parent = nullptr);

    inline void loadPCLayout();
    inline void loadTabletLayout();

    struct Margin {
        int left;
        int top;
        int right;
        int bottom;
    };

private:
    bool m_isTabletMode;
    QMap<LayoutComponent::Component, int> m_width;
    QMap<LayoutComponent::Component, int> m_height;
    QMap<LayoutComponent::Component, int> m_radius;
    QMap<LayoutComponent::Component, int> m_spacing;
    QMap<LayoutComponent::Component, Margin> m_margin;
};

/**
 * 注册到qml系统中，通过Helper与全局LayoutConfig进行通信。自动，动态修改界面布局
 */
class LayoutHelper : public QObject
{
    Q_OBJECT
    Q_PROPERTY(LayoutComponent::Component componentId READ getComponent WRITE setComponent NOTIFY componentChanged)
    Q_PROPERTY(int width READ getWidth NOTIFY layoutChanged)
    Q_PROPERTY(int height READ getHeight NOTIFY layoutChanged)
    Q_PROPERTY(int radius READ getRadius NOTIFY layoutChanged)
    Q_PROPERTY(int spacing READ getSpacing NOTIFY layoutChanged)
    Q_PROPERTY(int leftMargin READ getLeftMargin NOTIFY layoutChanged)
    Q_PROPERTY(int topMargin READ getTopMargin NOTIFY layoutChanged)
    Q_PROPERTY(int rightMargin READ getRightMargin NOTIFY layoutChanged)
    Q_PROPERTY(int bottomMargin READ getBottomMargin NOTIFY layoutChanged)

public:
    explicit LayoutHelper(QObject *parent = nullptr);

    void setComponent(LayoutComponent::Component component);
    LayoutComponent::Component getComponent();

    int getWidth();
    int getHeight();
    int getRadius();
    int getSpacing();

    int getLeftMargin();
    int getTopMargin();
    int getRightMargin();
    int getBottomMargin();

Q_SIGNALS:
    void layoutChanged();
    void componentChanged();

private:
    LayoutConfig *m_layoutConfig = nullptr;
    LayoutComponent::Component m_component = LayoutComponent::Undefined;
};

class SidebarGeometryController : public QObject
{
    Q_OBJECT
    friend class LayoutConfig;
public:
    static SidebarGeometryController* getInstance(QObject* parent = nullptr);

    // 侧边栏窗口内部边距
    Q_INVOKABLE qint32 sidebarWindowPadding();
    // 滑动出现最小阈值
    Q_INVOKABLE qint32 minimumThreshold();
    // 主屏幕的右侧边界
    Q_INVOKABLE qint32 primaryScreenRight();
    // 侧边栏窗口的窗口大小
    Q_INVOKABLE QRect sidebarWindowGeometry();
    Q_INVOKABLE QRect sidebarContentGeometry();

    // 设置窗口以设置模糊特效
    Q_INVOKABLE void updateWindowGeometry(QWindow *window);

Q_SIGNALS:
    void geometryChanged();

private Q_SLOTS:
    void updateSidebarGeometrySlot();

private:
    explicit SidebarGeometryController(QObject* parent = nullptr);
    inline void excludePanel(QRect &rect) const;
    inline void relocationSidebar(QRect &rect) const;
    inline void resizeSidebar(QRect &rect) const;
    inline void resizeContent(QRect &sidebarRect);

private:
    qint32 m_padding = 8;
    qint32 m_minimumThreshold = 100;
    qint32 m_primaryScreenRight = 0;
    bool   m_isTabletMode = false;
    QRect  m_sidebarWindowGeometry = {0, 0, 0, 0};
    QRect  m_sidebarContentGeometry = {0, 0, 0, 0};
};

} // UkuiShortcut

#endif //UKUI_SIDEBAR_SIDEBAR_UI_CONFIG_H
